// CDN Provider Interface
export interface CDNProvider {
	name: string;
	displayName: string;
	checkIp: (ip: string) => boolean;
	warningMessage: string;
}

const isIPInCIDR = (ip: string, cidr: string): boolean => {
	const [network, prefixLength] = cidr.split("/");
	if (!network || !prefixLength) return false;
	const prefix = Number.parseInt(prefixLength, 10);

	// Convert IP addresses to 32-bit integers
	const ipToInt = (ipStr: string): number => {
		return (
			ipStr
				.split(".")
				.reduce((acc, octet) => (acc << 8) + Number.parseInt(octet, 10), 0) >>>
			0
		);
	};

	const ipInt = ipToInt(ip);
	const networkInt = ipToInt(network);
	const mask = (0xffffffff << (32 - prefix)) >>> 0;

	return (ipInt & mask) === (networkInt & mask);
};

// Cloudflare IP ranges
// https://www.cloudflare.com/ips-v4
const CLOUDFLARE_IP_RANGES = [
	"173.245.48.0/20",
	"103.21.244.0/22",
	"103.22.200.0/22",
	"103.31.4.0/22",
	"141.101.64.0/18",
	"108.162.192.0/18",
	"190.93.240.0/20",
	"188.114.96.0/20",
	"197.234.240.0/22",
	"198.41.128.0/17",
	"162.158.0.0/15",
	"104.16.0.0/13",
	"104.24.0.0/14",
	"172.64.0.0/13",
	"131.0.72.0/22",
];

// Fastly IP ranges
// https://api.fastly.com/public-ip-list
const FASTLY_IP_RANGES = [
	"23.235.32.0/20",
	"43.249.72.0/22",
	"103.244.50.0/24",
	"103.245.222.0/23",
	"103.245.224.0/24",
	"104.156.80.0/20",
	"140.248.64.0/18",
	"140.248.128.0/17",
	"146.75.0.0/17",
	"151.101.0.0/16",
	"157.52.64.0/18",
	"167.82.0.0/17",
	"167.82.128.0/20",
	"167.82.160.0/20",
	"167.82.224.0/20",
	"172.111.64.0/18",
	"185.31.16.0/22",
	"199.27.72.0/21",
	"199.232.0.0/16",
];

// Bunny CDN IP addresses
// https://bunnycdn.com/api/system/edgeserverlist
const BUNNY_CDN_IPS = new Set([
	"89.187.188.227",
	"89.187.188.228",
	"139.180.134.196",
	"89.187.162.249",
	"89.187.162.242",
	"185.102.217.65",
	"185.93.1.243",
	"156.146.40.49",
	"185.59.220.199",
	"185.59.220.198",
	"195.181.166.158",
	"185.180.12.68",
	"138.199.24.209",
	"138.199.24.211",
	"79.127.216.111",
	"79.127.216.112",
	"89.187.169.47",
	"138.199.24.218",
	"185.40.106.117",
	"200.25.45.4",
	"200.25.57.5",
	"193.162.131.1",
	"200.25.11.8",
	"200.25.53.5",
	"200.25.13.98",
	"41.242.2.18",
	"200.25.62.5",
	"200.25.38.69",
	"200.25.42.70",
	"200.25.36.166",
	"194.242.11.186",
	"94.20.154.22",
	"185.93.1.244",
	"143.244.49.177",
	"138.199.46.66",
	"138.199.37.227",
	"138.199.37.231",
	"138.199.37.230",
	"138.199.37.229",
	"138.199.46.69",
	"138.199.46.68",
	"138.199.46.67",
	"185.93.1.246",
	"138.199.37.232",
	"195.181.163.196",
	"107.182.163.162",
	"195.181.163.195",
	"84.17.46.53",
	"212.102.40.114",
	"84.17.46.54",
	"138.199.40.58",
	"143.244.38.134",
	"143.244.38.136",
	"185.152.64.17",
	"84.17.59.115",
	"89.187.165.194",
	"138.199.15.193",
	"37.19.216.130",
	"185.93.1.247",
	"185.93.3.244",
	"143.244.49.179",
	"143.244.49.180",
	"138.199.9.104",
	"185.152.66.243",
	"143.244.49.178",
	"169.150.221.147",
	"200.25.18.73",
	"84.17.63.178",
	"200.25.32.131",
	"37.19.207.34",
	"37.19.207.38",
	"192.189.65.146",
	"143.244.45.177",
	"185.93.1.249",
	"185.93.1.250",
	"169.150.215.115",
	"209.177.87.197",
	"156.146.56.162",
	"156.146.56.161",
	"185.93.2.246",
	"185.93.2.245",
	"212.102.40.113",
	"185.93.2.244",
	"143.244.50.82",
	"143.244.50.83",
	"156.146.56.163",
	"129.227.217.178",
	"129.227.217.179",
	"200.25.69.94",
	"200.25.16.103",
	"102.67.138.155",
	"156.146.43.65",
	"195.181.163.203",
	"195.181.163.202",
	"156.146.56.169",
	"156.146.56.170",
	"156.146.56.166",
	"156.146.56.171",
	"169.150.207.210",
	"156.146.56.167",
	"143.244.50.84",
	"143.244.50.85",
	"143.244.50.86",
	"143.244.50.87",
	"156.146.56.168",
	"169.150.207.211",
	"212.102.50.59",
	"146.185.248.15",
	"143.244.50.90",
	"143.244.50.91",
	"143.244.50.88",
	"143.244.50.209",
	"143.244.50.213",
	"143.244.50.214",
	"143.244.49.183",
	"143.244.50.89",
	"143.244.50.210",
	"143.244.50.211",
	"143.244.50.212",
	"5.42.206.66",
	"94.46.27.186",
	"169.150.207.213",
	"169.150.207.214",
	"169.150.207.215",
	"169.150.207.212",
	"169.150.219.114",
	"169.150.202.210",
	"169.150.242.193",
	"185.93.1.251",
	"169.150.207.216",
	"169.150.207.217",
	"169.150.238.19",
	"102.219.126.20",
	"156.59.66.182",
	"122.10.251.130",
	"185.24.11.18",
	"138.199.36.7",
	"138.199.36.8",
	"138.199.36.9",
	"138.199.36.10",
	"138.199.36.11",
	"138.199.37.225",
	"84.17.46.49",
	"84.17.37.217",
	"169.150.225.35",
	"169.150.225.36",
	"169.150.225.37",
	"169.150.225.38",
	"169.150.225.39",
	"169.150.225.34",
	"169.150.236.97",
	"169.150.236.98",
	"169.150.236.99",
	"169.150.236.100",
	"93.189.63.149",
	"143.244.56.49",
	"143.244.56.50",
	"143.244.56.51",
	"169.150.247.40",
	"169.150.247.33",
	"169.150.247.34",
	"169.150.247.35",
	"169.150.247.36",
	"169.150.247.37",
	"169.150.247.38",
	"169.150.247.39",
	"38.142.94.218",
	"87.249.137.52",
	"38.104.169.186",
	"66.181.163.74",
	"84.17.38.227",
	"84.17.38.228",
	"84.17.38.229",
	"84.17.38.230",
	"84.17.38.231",
	"84.17.38.232",
	"169.150.225.41",
	"169.150.225.42",
	"169.150.249.162",
	"169.150.249.163",
	"169.150.249.164",
	"169.150.249.165",
	"169.150.249.166",
	"169.150.249.167",
	"169.150.249.168",
	"169.150.249.169",
	"185.131.64.124",
	"103.112.0.22",
	"37.236.234.2",
	"169.150.252.209",
	"212.102.46.118",
	"192.169.120.162",
	"93.180.217.214",
	"37.19.203.178",
	"107.155.47.146",
	"193.201.190.174",
	"156.59.95.218",
	"129.227.186.154",
	"195.238.127.98",
	"200.25.22.6",
	"204.16.244.92",
	"200.25.70.101",
	"139.180.209.182",
	"103.108.231.41",
	"103.108.229.5",
	"103.216.220.9",
	"169.150.225.40",
	"212.102.50.49",
	"212.102.50.52",
	"109.61.83.242",
	"109.61.83.243",
	"212.102.50.50",
	"169.150.225.43",
	"45.125.247.57",
	"103.235.199.170",
	"128.1.35.170",
	"38.32.110.58",
	"169.150.220.228",
	"169.150.220.229",
	"169.150.220.230",
	"169.150.220.231",
	"138.199.4.179",
	"207.211.214.145",
	"109.61.86.193",
	"103.214.20.95",
	"178.175.134.51",
	"138.199.4.178",
	"172.255.253.140",
	"185.24.11.19",
	"109.61.83.244",
	"109.61.83.245",
	"84.17.38.250",
	"84.17.38.251",
	"146.59.69.202",
	"146.70.80.218",
	"200.25.80.74",
	"79.127.213.214",
	"79.127.213.215",
	"79.127.213.216",
	"79.127.213.217",
	"195.69.140.112",
	"109.61.83.247",
	"109.61.83.246",
	"185.93.2.248",
	"109.61.83.249",
	"109.61.83.250",
	"109.61.83.251",
	"46.199.75.115",
	"141.164.35.160",
	"109.61.83.97",
	"109.61.83.98",
	"109.61.83.99",
	"129.227.179.18",
	"185.180.14.250",
	"152.89.160.26",
	"5.189.202.62",
	"98.98.242.142",
	"156.59.92.126",
	"84.17.59.117",
	"79.127.216.66",
	"79.127.204.113",
	"79.127.237.132",
	"169.150.236.104",
	"169.150.236.105",
	"37.27.135.61",
	"158.51.123.205",
	"156.146.43.70",
	"156.146.43.71",
	"156.146.43.72",
	"180.149.231.175",
	"185.93.2.243",
	"143.244.56.52",
	"143.244.56.53",
	"143.244.56.54",
	"143.244.56.55",
	"143.244.56.56",
	"143.244.56.57",
	"143.244.56.58",
	"144.76.236.44",
	"88.198.57.50",
	"78.46.69.199",
	"136.243.16.49",
	"138.201.86.122",
	"136.243.42.90",
	"88.99.95.221",
	"178.63.2.112",
	"5.9.98.45",
	"136.243.42.10",
	"169.150.236.106",
	"169.150.236.107",
	"185.93.1.242",
	"185.93.1.245",
	"143.244.60.193",
	"195.181.163.194",
	"79.127.188.193",
	"79.127.188.196",
	"79.127.188.194",
	"79.127.188.195",
	"104.166.144.106",
	"156.59.126.78",
	"185.135.85.154",
	"38.54.5.37",
	"38.54.3.92",
	"185.165.170.74",
	"207.121.75.132",
	"207.121.80.12",
	"207.121.80.172",
	"207.121.90.60",
	"138.199.24.219",
	"185.93.2.251",
	"138.199.46.65",
	"154.95.86.76",
	"5.9.99.73",
	"78.46.92.118",
	"144.76.65.213",
	"78.46.156.89",
	"88.198.9.155",
	"144.76.79.22",
	"37.19.207.37",
	"208.83.234.224",
	"79.127.237.104",
	"79.127.243.187",
	"45.156.248.73",
	"79.127.134.225",
	"79.127.134.226",
	"79.127.134.227",
	"79.127.134.228",
	"79.127.134.229",
	"79.127.134.230",
	"79.127.134.231",
	"79.127.134.130",
	"79.127.134.131",
	"79.127.134.132",
	"79.127.134.234",
	"79.127.134.235",
	"185.111.111.154",
	"185.111.111.155",
	"185.111.111.156",
	"185.111.111.157",
	"185.111.111.158",
	"185.111.111.159",
	"185.111.111.160",
	"141.227.142.242",
	"94.128.254.166",
	"195.206.229.69",
	"200.25.86.90",
	"148.113.190.161",
	"46.151.194.242",
	"46.151.194.243",
	"212.102.40.120",
	"213.170.143.100",
	"154.93.86.71",
	"143.244.60.196",
	"143.244.60.197",
	"143.244.60.195",
	"79.127.134.129",
	"79.127.134.133",
	"152.233.22.97",
	"152.233.22.98",
	"152.233.22.100",
	"152.233.22.99",
	"152.233.22.101",
	"152.233.22.102",
	"152.233.22.103",
	"116.202.155.146",
	"116.202.193.178",
	"116.202.224.168",
	"188.40.126.227",
	"88.99.26.189",
	"168.119.39.238",
	"88.99.26.97",
	"168.119.12.188",
	"176.9.139.55",
	"142.132.223.79",
	"142.132.223.80",
	"142.132.223.81",
	"46.4.116.17",
	"46.4.119.81",
	"167.235.114.167",
	"159.69.68.171",
	"178.63.21.52",
	"46.4.120.152",
	"116.202.80.247",
	"5.9.71.119",
	"195.201.11.156",
	"78.46.123.17",
	"46.4.113.143",
	"136.243.2.236",
	"195.201.81.217",
	"148.251.42.123",
	"94.130.68.122",
	"88.198.22.103",
	"46.4.102.90",
	"157.90.180.205",
	"162.55.135.11",
	"195.201.109.59",
	"148.251.41.244",
	"116.202.235.16",
	"128.140.70.141",
	"78.46.74.86",
	"78.46.74.85",
	"178.63.41.242",
	"178.63.41.247",
	"178.63.41.234",
	"104.237.53.74",
	"104.237.54.154",
	"104.237.51.58",
	"64.185.235.90",
	"64.185.234.114",
	"64.185.232.194",
	"64.185.232.178",
	"64.185.232.82",
	"103.60.15.169",
	"103.60.15.170",
	"103.60.15.171",
	"103.60.15.172",
	"103.60.15.173",
	"103.60.15.162",
	"103.60.15.163",
	"103.60.15.164",
	"103.60.15.165",
	"103.60.15.166",
	"103.60.15.167",
	"103.60.15.168",
	"176.9.139.94",
	"148.251.129.132",
	"148.251.131.73",
	"148.251.131.74",
	"136.243.70.170",
	"148.251.131.238",
	"109.248.43.116",
	"109.248.43.117",
	"109.248.43.162",
	"109.248.43.163",
	"109.248.43.164",
	"109.248.43.165",
	"49.12.71.27",
	"49.12.0.158",
	"78.47.94.156",
	"109.248.43.159",
	"109.248.43.160",
	"109.248.43.208",
	"109.248.43.179",
	"109.248.43.232",
	"109.248.43.231",
	"109.248.43.241",
	"109.248.43.236",
	"109.248.43.240",
	"109.248.43.103",
	"116.202.118.194",
	"116.202.80.29",
	"159.69.57.80",
	"139.180.129.216",
	"139.99.174.7",
	"89.187.169.18",
	"143.244.38.133",
	"89.187.179.7",
	"169.150.213.50",
	"143.244.62.213",
	"185.93.3.246",
	"195.181.163.198",
	"185.152.64.19",
	"84.17.37.211",
	"212.102.50.54",
	"212.102.46.115",
	"169.150.238.21",
	"169.150.207.51",
	"169.150.207.49",
	"84.17.38.226",
	"84.17.38.225",
	"37.19.222.248",
	"37.19.222.249",
	"169.150.247.139",
	"169.150.247.177",
	"169.150.247.178",
	"212.102.46.119",
	"84.17.38.234",
	"84.17.38.233",
	"169.150.247.179",
	"169.150.247.180",
	"169.150.247.181",
	"169.150.247.182",
	"169.150.247.183",
	"169.150.247.138",
	"169.150.247.184",
	"169.150.247.185",
	"212.102.43.88",
	"89.187.169.26",
	"109.61.89.57",
	"109.61.89.58",
	"109.61.83.241",
	"84.17.38.243",
	"84.17.38.244",
	"84.17.38.246",
	"84.17.38.247",
	"84.17.38.245",
	"143.244.38.129",
	"84.17.38.248",
	"89.187.176.34",
	"185.152.64.23",
	"79.127.213.209",
	"79.127.213.210",
	"84.17.37.209",
	"156.146.43.68",
	"185.93.3.243",
	"79.127.219.198",
	"138.199.33.57",
	"79.127.242.89",
	"138.199.4.136",
	"169.150.220.235",
	"138.199.4.129",
	"138.199.4.177",
	"37.19.222.34",
	"46.151.193.85",
	"79.127.237.99",
	"212.104.158.30",
	"212.104.158.31",
	"212.104.158.32",
	"212.104.158.33",
	"212.104.158.34",
	"212.104.158.28",
	"212.104.158.29",
	"212.104.158.35",
	"212.104.158.36",
	"212.104.158.37",
	"212.104.158.17",
	"212.104.158.18",
	"212.104.158.19",
	"212.104.158.20",
	"212.104.158.21",
	"212.104.158.22",
	"212.104.158.24",
	"212.104.158.26",
	"89.187.184.177",
	"89.187.184.179",
	"89.187.184.173",
	"89.187.184.178",
	"89.187.184.176",
	"212.104.158.25",
	"212.104.158.27",
	"212.104.158.67",
	"212.104.158.10",
	"212.104.158.12",
	"212.104.158.64",
	"212.104.158.16",
	"212.104.158.23",
	"212.104.158.54",
]);

// Arvancloud IP ranges
// https://www.arvancloud.ir/fa/ips.txt
const ARVANCLOUD_IP_RANGES = [
	"185.143.232.0/22",
	"188.229.116.16/29",
	"94.101.182.0/27",
	"2.144.3.128/28",
	"89.45.48.64/28",
	"37.32.16.0/27",
	"37.32.17.0/27",
	"37.32.18.0/27",
	"37.32.19.0/27",
	"185.215.232.0/22",
	"178.131.120.48/28",
];

const CDN_PROVIDERS: CDNProvider[] = [
	{
		name: "cloudflare",
		displayName: "Cloudflare",
		checkIp: (ip: string) =>
			CLOUDFLARE_IP_RANGES.some((range) => isIPInCIDR(ip, range)),
		warningMessage:
			"Domain is behind Cloudflare - actual IP is masked by Cloudflare proxy",
	},
	{
		name: "bunnycdn",
		displayName: "Bunny CDN",
		checkIp: (ip: string) => BUNNY_CDN_IPS.has(ip),
		warningMessage:
			"Domain is behind Bunny CDN - actual IP is masked by CDN proxy",
	},
	{
		name: "fastly",
		displayName: "Fastly",
		checkIp: (ip: string) =>
			FASTLY_IP_RANGES.some((range) => isIPInCIDR(ip, range)),
		warningMessage:
			"Domain is behind Fastly - actual IP is masked by CDN proxy",
	},
	{
		name: "arvancloud",
		displayName: "Arvancloud",
		checkIp: (ip: string) =>
			ARVANCLOUD_IP_RANGES.some((range) => isIPInCIDR(ip, range)),
		warningMessage:
			"Domain is behind Arvancloud - actual IP is masked by CDN proxy",
	},
];

export const detectCDNProvider = (ip: string): CDNProvider | null => {
	return CDN_PROVIDERS.find((provider) => provider.checkIp(ip)) || null;
};
